﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;

namespace DynCMS.NET.Infrastructure.IOC.Windsor
{
    internal class IOCProvider : IIOCProvider
    {
        public void Initialize()
        {
            BuildContainer();
            ControllerBuilder.Current.SetControllerFactory(new Impl.ControllerFactory(_container.Kernel));
            DependencyResolver.SetResolver(new Impl.DependencyResolver(new WindsorServiceProvider(_container)));
            this.Register<ModelMetadataProvider, CachedDataAnnotationsModelMetadataProvider>("CachedDataAnnotationsModelMetadataProvider");
            ModelMetadataProviders.Current = new CachedDataAnnotationsModelMetadataProvider();
        }

        Castle.Windsor.IWindsorContainer _container;

        private Castle.Windsor.IWindsorContainer Container
        {
            get
            {
                //if (_container == null) BuildContainer();
                return _container;
            }
        }

        private void BuildContainer()
        {
            _container = new WindsorContainer();
            _container.Install(FromAssembly.This());
            //var installers = FromAssembly.InThisApplication();
            _container.Install(FromAssembly.Named("DynCMS.NET.DataAccess"));
        }

        public IOCProvider()
        {
        }

        public Type Resolve<Type>()
        {
            return Container.Resolve<Type>();
        }

        public Type Resolve<Type>(string name)
        {
            return Container.Resolve<Type>(name);
        }

        public void Register<IContract, IImplementation>()
            where IImplementation : IContract
            where IContract : class
        {
            this.Register<IContract, IImplementation>(null);
        }

        public void Register<IContract, IImplementation>(string name)
            where IContract : class
            where IImplementation : IContract
        {
            var registration = new ComponentRegistration<IContract>(typeof(IContract));
            registration.ImplementedBy<IImplementation>();

            // TODO: enable other lifestyles
            //registration = registration.LifestylePerWebRequest();
            registration = registration.LifestyleTransient();

            if (!string.IsNullOrEmpty(name))
            {
                registration.Named(name);
            }
            Container.Register(registration);
        }

        public void RegisterAllFromAssemblyContaining<Type>()
        {
            Container.Register(Classes.FromAssemblyContaining<Type>()
                .IncludeNonPublicTypes()
                .Pick()
                .WithServiceAllInterfaces()
                .WithServiceSelf()
                .LifestylePerThread());
        }
    }
}